#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <fstream>
#include <sys/stat.h>

const std::string SEP      = "\n";
const std::string WEB_ROOT = "wwwroot/";

struct http_request
{
    std::string _method;
    std::string _url;
    std::string _version;

    std::vector<std::string> _headers;
    std::string _content;

    std::string _path;

    http_request(const std::string& reqstr) { deserialize(reqstr); }

    void deserialize(const std::string reqstr)
    {
        std::stringstream reqss(reqstr);

        std::string line;
        getline(reqss, line);
        std::stringstream(line) >> _method >> _url >> _version;

        _path += WEB_ROOT;
        if (_url.back() == '/') _path += "index.html";
        else _path += _url;

        while (getline(reqss, line))
            _headers.push_back(line);

        getline(reqss, _content);      
    }
};

struct http_response
{
    http_response(const http_request& req) : _version("HTTP/1.0"), _path(req._path)
    {
        struct stat st;
        if (stat(_path.c_str(), &st) < 0)
        {
            _stcode = 404;
            _stdesc = "Not Found";
            _path = WEB_ROOT + "404.html";
        }
        else 
        { 
            _stcode = 200;
            _stdesc = "OK";
        }

        std::ifstream ifs(_path, std::ios_base::binary);
        std::string line;
        while (getline(ifs, line))
            _content += line;

        _headers.push_back("Content-Type: " + get_type());
        _headers.push_back("Content-Length: " + std::to_string(_content.size()));
        _headers.push_back("Set-Cookie: name=zhangsan");
        _headers.push_back("Set-Cookie: passwd=1234");
        _headers.push_back("Set-Cookie: session_id=141234asdfjasdkfj12903423jklsdaffja8912347");
    }

    std::string _version;
    int _stcode;
    std::string _stdesc;

    std::vector<std::string> _headers;
    std::string _path;
    std::string _content;

    std::string serialize()
    {

        std::stringstream ss;

        ss << _version << ' ' << _stcode << ' ' << _stdesc << SEP;
        for (auto& e : _headers)
            ss << e << SEP;
        ss << SEP;
        ss << _content;

        return ss.str();
    }

    std::string get_type()
    {
        size_t pos = _path.rfind('.');
        std::string suffix = _path.substr(pos);
        if (suffix == ".html") return "text/html";
        if (suffix == ".css")  return "text/css";
        if (suffix == ".js")   return "application/x-javascript";
        if (suffix == ".png")  return "image/png";
        if (suffix == ".jpg")  return "image/jpeg";
        if (suffix == ".gif")  return "image/gif";
        else return "text/plain";
    }
};


